const usersProxy = require('../proxy/users')
const clientsProxy = require('../proxy/client')
const redisProxy = require('../common/redis')
const generateUserRoles = require('../controller/users').generateUserRoles
const fetchUserFirstTeam = require('../controller/users').fetchUserFirstTeam
const crypto = require('../common/crypto.api')
const jwt = require('jsonwebtoken')

exports.getAccessToken = async function(req, res, next) {
  const { phone } = req.body
  console.log(`phone is ${phone}`)
  const userId = await usersProxy.validateUserByPassword(phone, req.body.password)
  if (userId) {
    req.session.token = 'SSAS-Token-' + userId
    redisProxy.set(crypto.Hash('ssas' + userId), req.session.id)
    res.json({ token: req.session.token })
  } else {
    res.statusMessage = 'error phone or password'
    res.status(204).end()
  }
}

exports.destroyAccessToken = function(req, res, next) {
  if (req.session.token) {
    const userId = req.session.token.substr(11)
    console.log(`[DEBUG]${userId} logout`)
    req.session.destroy()
    redisProxy.del(crypto.Hash('ssas' + userId))
  }
  res.json({ status: 0, info: 'had logout', body: null })
}

exports.generateAuthorizationCode = async function(req, res, next) {
  const { phone, password, clientId, redirectUri, responseType } = req.body
  if (!responseType || responseType !== 'code') return res.sendStatus(400)
  const validClient = await clientsProxy.validate(clientId)
  if (validClient) {
    // Client已接入SSAS平台
    const userId = await usersProxy.validateUserByPassword(phone, password)
    if (userId) {
      const code = crypto.Hash(phone + clientId + redirectUri + (new Date()).getTime())
      redisProxy.set(code, JSON.stringify({ clientId, redirectUri, userId }), 'EX', 600)
      if (clientId === 'V9IERd6YtVFURD077tqWnlNDjW0=') {
        // SSAS
        res.status(200).json({ code })
      } else {
        // third party
        res.redirect(`${redirectUri}?code=${code}`)
      }
    } else {
      res.statusMessage = 'error phone or password'
      res.status(204).end()
    }
  } else {
    res.status(402).end()
  }
}

exports.generateTokens = async function(req, res, next) {
  const { grantType, code, redirectUri, clientId } = req.body
  if (!grantType || grantType !== 'authorization_code') return res.sendStatus(400)
  const valid = await redisProxy.get(code)
  if (valid) {
    const data = JSON.parse(valid)
    if (data.clientId === clientId && data.redirectUri === redirectUri) {
      // generate ac token and rf token
      const { userId } = data
      const roles = await generateUserRoles(userId)
      const team = (await fetchUserFirstTeam(userId))
      const teamId = team ? team.team : null
      const accessToken = jwt.sign({ userId, roles, teamId }, 'SSAS.COM.PRIVATE-KEY', { expiresIn: '10m' })
      const refreshToken = jwt.sign({ userId, clientId, teamId }, 'SSAS.COM.PRIVATE-KEY', { expiresIn: '1d', issuer: 'SSAS.COM' })
      res.set({
        'Cache-Control': 'no-store',
        'Pragma': 'no-cache'
      })
      res.cookie('X_SSAS_AccessToken', accessToken, { httpOnly: true })
      res.cookie('X_SSAS_RefreshToken', refreshToken, { httpOnly: true })
      res.cookie('login', 1)
      res.cookie('n', userId)
      if (teamId) res.cookie('jl', teamId.toString())
      res.json({ userId, accessToken, refreshToken, tokenType: 'Bearer' })
    } else {
      res.status(402).end()
    }
  } else {
    res.status(227).end()
  }
}

exports.refreshAccessToken = async(req, res, next) => {
  const { refreshToken } = req.body
  try {
    const accessToken = await this.refreshWith(refreshToken)
    res.json({ accessToken })
  } catch (err) {
    console.log(`[ERROR]refreshAccessToken failed:${err.message}`)
    res.status(401).end()
  }
}

exports.refreshWith = async function(refreshToken) {
  try {
    const decoded = jwt.verify(refreshToken, 'SSAS.COM.PRIVATE-KEY')
    if (decoded.iss === 'SSAS.COM') {
      const { userId, teamId } = decoded
      // console.log(`[REFRESH] user:${userId}, team:${teamId}`)
      const roles = await generateUserRoles(userId)
      const accessToken = jwt.sign({ userId, roles, teamId }, 'SSAS.COM.PRIVATE-KEY', { expiresIn: '10m' })
      return accessToken
    } else {
      throw new Error(`Decoded Failed! wrong issuer`)
    }
  } catch (err) {
    throw err
  }
}

exports.refreshTokenById = async function(userId, teamId) {
  try {
    const roles = await generateUserRoles(userId)
    const accessToken = jwt.sign({ userId, roles, teamId }, 'SSAS.COM.PRIVATE-KEY', { expiresIn: '10m' })
    return { accessToken, roles }
  } catch (err) {
    throw err
  }
}
